package ZJX_net

import (
	"TCP-sever/interface"
	"TCP-sever/utils"
	"bytes"
	"encoding/binary"
	"fmt"
	"net"
)

//IServer接口实现
type Server struct {
	IPVersion string
	Ip        string
	Port      int
	Name      string

	//可以自定义的路由方法
	Mh ZJX_interface.IMsgHandler
	//连接管理模块
	connManager ZJX_interface.IConnManager
}

//启动服务器
func (s *Server) Start() {
	fmt.Printf("[Start] Server listen Ip:%s, Port:%d\n", s.Ip, s.Port)
	//获取TCP的Addr

	go s.Mh.StartWorkerPool()

	go func() {
		//得到Addr，以便后续得到连接
		addr, err := net.ResolveTCPAddr(s.IPVersion, fmt.Sprintf("%s:%d", s.Ip, s.Port))

		if err != nil {
			fmt.Println("resolve tcp addr error: ", err)
			return
		}
		//得到监听目标地址的套接字
		listener, err := net.ListenTCP(s.IPVersion, addr)

		if err != nil {
			fmt.Println("listen", s.IPVersion, "err", err)
			return
		}
		fmt.Println("start Server success. name:", s.Name)

		var cid uint32
		cid = 0
		for {
			//监听目标地址，得到连接
			conn, err := listener.AcceptTCP()
			if err != nil {
				fmt.Println("get conn err", err)
				return
			}

			//判断是否超过最大连接数，如果超过了则拒绝连接
			if s.connManager.Size() >= utils.GlobalObject.MaxConn {
				//TODO 给用户发送消息通知连接失败
				s := "Connection fail, too many conn"
				len := uint32(len(s))
				Id := uint32(0)
				retMsg := bytes.NewBuffer([]byte{})

				dataMsg := make([]byte, len)
				for i := uint32(0); i < len; i++ {
					dataMsg[i] = s[i]
				}

				if err := binary.Write(retMsg, binary.LittleEndian, len); err != nil {
				}
				if err := binary.Write(retMsg, binary.LittleEndian, Id); err != nil {
				}
				if err := binary.Write(retMsg, binary.LittleEndian, dataMsg); err != nil {
				}
				conn.Write(retMsg.Bytes())
				conn.Close()
				continue
			}

			dealConn := NewConnection(s, conn, cid, s.Mh)
			cid++
			//处理连接
			dealConn.Start()
		}
	}()
}

func (s *Server) Stop() {
	//TODO 回收资源，停止服务
	fmt.Println("Server Stop...........")
	s.connManager.Clear()
}

func (s *Server) Server() {
	//启动服务
	s.Start()

	//TODO 启动后的额外任务

	//阻塞
	select {}
}

func (s *Server) AddRouter(msgId uint32, router ZJX_interface.IRouter) {
	s.Mh.AddRouter(msgId, router)
}

func (s *Server) GetConnManager() ZJX_interface.IConnManager {
	return s.connManager
}

func NewServer() ZJX_interface.IServer {
	s := &Server{
		IPVersion:   "tcp4",
		Ip:          utils.GlobalObject.Host,
		Port:        utils.GlobalObject.Port,
		Name:        utils.GlobalObject.Name,
		Mh:          NewMsgHandler(),
		connManager: NewConnManager(),
	}

	return s
}
